﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;

namespace Basic
{
    /// <summary>
    /// 针对可读写目录、文件的操作
    /// </summary>
    public class FileHelper
    {
        /// <summary>
        /// 可读写目录下，获得指定路径下满足条件的所有文件的相对路径(不含子文件夹)
        /// 若cutLength为0，则是基于fullPath的全路径
        /// </summary>
        /// <param name="result"></param>
        /// <param name="dirPath"></param>
        /// <param name="cutLength"></param>
        /// <param name="fileSuffixLimit">如.png; 若为null，则无文件名后缀限制</param>
        /// <param name="fileSuffixIgnore">如.meta; 若为null，则无文件名后缀忽略限制</param>
        public static void GetDirectoryFileRelativePathNoSubDir(List<string> result, string dirPath, int cutLength,
            List<string> fileSuffixLimit, List<string> fileSuffixIgnore)
        {
            if (string.IsNullOrEmpty(dirPath) || !Directory.Exists(dirPath) || cutLength < 0)
            {
                return;
            }

            dirPath = dirPath.Replace('\\', '/');

            string relativePath = dirPath.Substring(cutLength);
            if (!relativePath.EndsWith("/"))
            {
                relativePath += "/";
            }

            DirectoryInfo root = new DirectoryInfo(dirPath);
            foreach (FileInfo f in root.GetFiles())
            {
                bool ignore = false;
                if (fileSuffixIgnore != null)
                {
                    for (int i = 0; i < fileSuffixIgnore.Count; ++i)
                    {
                        if (f.Name.EndsWith(fileSuffixIgnore[i], StringComparison.Ordinal))
                        {
                            ignore = true;
                            break;
                        }
                    }
                }
                if (ignore)
                {
                    continue;
                }

                if (fileSuffixLimit != null)
                {
                    ignore = true;
                    for (int i = 0; i < fileSuffixLimit.Count; ++i)
                    {
                        if (f.Name.EndsWith(fileSuffixLimit[i], StringComparison.Ordinal))
                        {
                            ignore = false;
                            break;
                        }
                    }
                }
                if (ignore)
                {
                    continue;
                }

                result.Add(relativePath + f.Name);
            }
        }

        /// <summary>
        /// 可读写目录下，获得指定路径下满足条件的所有文件的相对路径(含子文件夹)
        /// 若cutLength为0，则是基于fullPath的全路径
        /// </summary>
        /// <param name="result"></param>
        /// <param name="dirPath"></param>
        /// <param name="cutLength"></param>
        /// <param name="fileSuffixLimit">如.png; 若为null，则无文件名后缀限制</param>
        /// <param name="fileSuffixIgnore">如.meta; 若为null，则无文件名后缀忽略限制</param>
        /// <param name="subDirIgnore">忽略哪些子目录名称</param>
        public static void GetDirectoryFileRelativePath(List<string> result, string dirPath, int cutLength,
            List<string> fileSuffixLimit, List<string> fileSuffixIgnore, List<string> subDirIgnore)
        {
            if (string.IsNullOrEmpty(dirPath) || !Directory.Exists(dirPath) || cutLength < 0)
            {
                return;
            }

            GetDirectoryFileRelativePathNoSubDir(result, dirPath, cutLength, fileSuffixLimit, fileSuffixIgnore);

            DirectoryInfo root = new DirectoryInfo(dirPath);
            foreach (DirectoryInfo d in root.GetDirectories("*", SearchOption.AllDirectories))
            {
                bool ignore = false;
                if (subDirIgnore != null)
                {
                    var dirName = d.Name;
                    for (int i = 0; i < subDirIgnore.Count; ++i)
                    {
                        if (string.CompareOrdinal(dirName, subDirIgnore[i]) == 0)
                        {
                            ignore = true;
                            break;
                        }
                    }
                }

                if (!ignore)
                {
                    GetDirectoryFileRelativePathNoSubDir(result, d.FullName, cutLength, fileSuffixLimit, fileSuffixIgnore);
                }
            }
        }

        /// <summary>
        /// 可读写目录下，删除文件夹
        /// </summary>
        /// <param name="dirPath"></param>
        /// <param name="deleteDir"></param>
        /// <param name="deleteSubDir"></param>
        public static void DeleteDirectory(string dirPath, bool deleteDir, bool deleteSubDir)
        {
            if (Directory.Exists(dirPath))//如果 存在这个文件夹删除之
            {
                foreach (string path in Directory.GetFileSystemEntries(dirPath))
                {
                    if (File.Exists(path))
                    {
                        File.Delete(path);//直接删除其中的文件 
                    }
                    else if (deleteSubDir)
                    {
                        DeleteDirectory(path, true, deleteSubDir);//递归删除子文件夹 
                    }
                }

                if (deleteDir)
                {
                    Directory.Delete(dirPath);
                }
            }
        }

        /// <summary>
        /// 可读写目录下，若文件路径所在的目录不存在，则创建
        /// </summary>
        /// <param name="dirPath"></param>
        public static void CreateDirectoryForFilePath(string dirPath)
        {
            var dir = Path.GetDirectoryName(dirPath);
            if (!Directory.Exists(dir))
            {
                Directory.CreateDirectory(dir);
            }
        }

        /// <summary>
        /// 可读写目录下，删除目录下特定后缀的文件
        /// </summary>
        /// <param name="dirPath"></param>
        /// <param name="suffixLimit"></param>
        public static void DeleteFiles(string dirPath, List<string> suffixLimit)
        {
            if (Directory.Exists(dirPath))
            {
                foreach (string path in Directory.GetFileSystemEntries(dirPath))
                {
                    if (File.Exists(path))// 文件
                    {
                        bool delete = suffixLimit == null;
                        if (!delete && suffixLimit != null)
                        {
                            for (int i = 0; i < suffixLimit.Count; ++i)
                            {
                                if (path.EndsWith(suffixLimit[i], StringComparison.Ordinal))
                                {
                                    delete = true;
                                    break;
                                }
                            }
                        }

                        if (delete)
                        {
                            File.Delete(path);
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 可读写目录下，删除指定文件
        /// </summary>
        /// <param name="filePath"></param>
        public static void DeleteFile(string filePath)
        {
            if (File.Exists(filePath))
            {
                File.Delete(filePath);
            }
        }

        /// <summary>
        /// 可读写目录下，将文件夹下满足条件的所有文件，拷贝到目标目录下
        /// </summary>
        /// <param name="dirPathFrom"></param>
        /// <param name="dirPathTo"></param>
        /// <param name="clearBeforeCopy"></param>
        /// <param name="copySubDir">是否递归拷贝子目录</param>
        /// <param name="fileSuffixLimit">如.png; 若为null，则无文件名后缀限制</param>
        /// <param name="fileSuffixIgnore">如.meta; 若为null，则无文件名后缀忽略限制</param>
        /// <param name="subDirIgnore"></param>
        public static void CopyPath(string dirPathFrom, string dirPathTo, bool clearBeforeCopy, bool copySubDir,
            List<string> fileSuffixLimit, List<string> fileSuffixIgnore, List<string> subDirIgnore)
        {
            if (!Directory.Exists(dirPathTo))
            {
                Directory.CreateDirectory(dirPathTo);
            }

            if (clearBeforeCopy)
            {
                DeleteDirectory(dirPathTo, false, true);
            }

            dirPathFrom = dirPathFrom.Replace('\\', '/');
            if (!dirPathFrom.EndsWith("/", StringComparison.Ordinal))
            {
                dirPathFrom += "/";
            }

            dirPathTo = dirPathTo.Replace('\\', '/');
            if (!dirPathTo.EndsWith("/", StringComparison.Ordinal))
            {
                dirPathTo += "/";
            }

            List<string> files = new List<string>();
            if (copySubDir)
            {
                GetDirectoryFileRelativePath(files, dirPathFrom, dirPathFrom.Length, fileSuffixLimit, fileSuffixIgnore, subDirIgnore);
            }
            else
            {
                GetDirectoryFileRelativePathNoSubDir(files, dirPathFrom, dirPathFrom.Length, fileSuffixLimit, fileSuffixIgnore);
            }

            for (int i = 0; i < files.Count; ++i)
            {
                CopyFile(dirPathFrom + files[i], dirPathTo + files[i]);
            }
        }

        /// <summary>
        /// 可读写目录下，文件拷贝
        /// </summary>
        /// <param name="filePathFrom"></param>
        /// <param name="filePathTo"></param>
        public static void CopyFile(string filePathFrom, string filePathTo)
        {
            CreateDirectoryForFilePath(filePathTo);

            File.Copy(filePathFrom, filePathTo, true);
        }

        /// <summary>
        /// 可读写目录下，写文件
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="fileData"></param>
        public static void WriteFile(string filePath, byte[] fileData)
        {
            CreateDirectoryForFilePath(filePath);

            File.WriteAllBytes(filePath, fileData);
        }
        public static void WriteFile(string filePath, string fileData)
        {
            CreateDirectoryForFilePath(filePath);

            File.WriteAllText(filePath, fileData);
        }
        public static void WriteAllLines(string filePath, IEnumerable<string> fileData)
        {
            CreateDirectoryForFilePath(filePath);

            File.WriteAllLines(filePath, fileData);
        }

        /// <summary>
        /// 可读写目录下，追加内容到文件
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="fileData"></param>
        public static void AppendFile(string filePath, string fileData)
        {
            CreateDirectoryForFilePath(filePath);

            File.AppendAllText(filePath, fileData);
        }

        /// <summary>
        /// 可读写目录下，获取文件内容
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public static byte[] GetFileData(string filePath)
        {
            if (File.Exists(filePath))
            {
                return File.ReadAllBytes(filePath);
            }
            return null;
        }

        /// <summary>
        /// 可读写目录下，获取文件大小. 文件不存在时, 返回-1
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public static int GetFileSize(string filePath)
        {
            if (File.Exists(filePath))
            {
                var finfo = new FileInfo(filePath);
                if (finfo != null)
                {
                    return (int)finfo.Length;
                }
            }

            return -1;
        }

        /// <summary>
        /// 可读写目录下，文件是否存在
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public static bool IsFileExist(string filePath)
        {
            return File.Exists(filePath);
        }
    }
}
